package com.lightboat.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightboat.common.api.BaiDuJianKangApi;
import com.lightboat.common.config.properties.OpenApiCredentialProperties;
import com.lightboat.common.constant.RedisConstants;
import com.lightboat.common.core.domain.bo.AfterSaleOrderProductBo;
import com.lightboat.common.core.domain.bo.OrderProductBo;
import com.lightboat.common.core.text.Convert;
import com.lightboat.common.enums.MsgType;
import com.lightboat.common.enums.ProductType;
import com.lightboat.common.enums.RedisSnEnum;
import com.lightboat.common.exception.ServiceException;
import com.lightboat.common.utils.DateUtils;
import com.lightboat.common.utils.RedisSnGenerator;
import com.lightboat.common.utils.RedisUtils;
import com.lightboat.system.domain.*;
import com.lightboat.system.mapper.CrmAfterSaleMapper;
import com.lightboat.system.mapper.CrmOrderMapper;
import com.lightboat.system.mapper.CrmProductMapper;
import com.lightboat.system.mapper.CrmProductStockRecordMapper;
import com.lightboat.system.service.ICrmAfterSaleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * 售后Service业务层处理
 *
 * @author lightboat
 * @date 2025-09-09
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CrmAfterSaleServiceImpl extends ServiceImpl<CrmAfterSaleMapper, CrmAfterSale> implements ICrmAfterSaleService {

    private final CrmAfterSaleMapper crmAfterSaleMapper;
    private final CrmOrderMapper crmOrderMapper;
    private final OpenApiCredentialProperties apiCredentialProperties;
    private final CrmProductStockRecordMapper crmProductStockRecordMapper;
    private final CrmProductMapper crmProductMapper;

    /**
     * 查询售后
     *
     * @param afterSaleId 售后主键
     * @return 售后
     */
    @Override
    public CrmAfterSale selectCrmAfterSaleByAfterSaleId(Long afterSaleId) {
        return crmAfterSaleMapper.selectById(afterSaleId);
    }

    /**
     * 查询售后列表
     *
     * @param crmAfterSale 售后
     * @return 售后
     */
    @Override
    public List<CrmAfterSale> selectCrmAfterSaleList(CrmAfterSale crmAfterSale) {
        return crmAfterSaleMapper.selectCrmAfterSaleList(crmAfterSale);
    }

    /**
     * 新增售后
     *
     * @param crmAfterSale 售后
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertCrmAfterSale(CrmAfterSale crmAfterSale) {
        crmAfterSale.setCreateTime(DateUtils.getNowDate());
        // 如果是复购，直接加库存
        if (crmAfterSale.getAfterSaleType() == 2) {
            crmAfterSale.getGoods().parallelStream().forEach(item -> {
                RedisUtils.builder().redissonLock(RedisConstants.PRODUCT_PREFIX + item.getProductId(), () -> {
                    CrmProduct crmProduct = crmProductMapper.selectById(item.getProductId());
                    CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                    crmProductStockRecord.setProductId(item.getProductId());
                    crmProductStockRecord.setOrderId(crmAfterSale.getOrderId());
                    crmProductStockRecord.setOperationType(1);
                    crmProductStockRecord.setOrderStatus(3);
                    crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()));

                    if (crmProduct != null) {
                        Long stock = crmProduct.getStock();
                        crmProductStockRecord.setOriginalStock(stock);
                        long remainingStock = stock + crmProductStockRecord.getChangeQuantity();
                        crmProductStockRecord.setRemainingStock(remainingStock);

                        CrmProduct updateProduct = new CrmProduct();
                        updateProduct.setProductId(item.getProductId());
                        updateProduct.setStock(remainingStock);
                        crmProductMapper.updateById(updateProduct);
                    }
                    crmProductStockRecordMapper.insert(crmProductStockRecord);
                    return Boolean.TRUE;
                }, 3, 3, TimeUnit.SECONDS, "操作繁忙，请稍后~");
            });
        }
        return crmAfterSaleMapper.insert(crmAfterSale);
    }

    /**
     * 修改售后
     *
     * @param crmAfterSale 售后
     * @return 结果
     */
    @Override
    public int updateCrmAfterSale(CrmAfterSale crmAfterSale) {
        crmAfterSale.setUpdateTime(DateUtils.getNowDate());
        return crmAfterSaleMapper.updateById(crmAfterSale);
    }

    /**
     * 批量删除售后
     *
     * @param afterSaleIds 需要删除的售后主键
     * @return 结果
     */
    @Override
    public int deleteCrmAfterSaleByAfterSaleIds(Long[] afterSaleIds) {
        return crmAfterSaleMapper.deleteCrmAfterSaleByAfterSaleIds(afterSaleIds);
    }

    /**
     * 删除售后信息
     *
     * @param afterSaleId 售后主键
     * @return 结果
     */
    @Override
    public int deleteCrmAfterSaleByAfterSaleId(Long afterSaleId) {
        return crmAfterSaleMapper.deleteCrmAfterSaleByAfterSaleId(afterSaleId);
    }

    @Override
    public int listeningAfterSale(JSONObject data, JSONObject extra, int status) {
        BaiDuJianKangApi.AfterSalePushMessageDTO afterSalePushMessageDTO = data.to(BaiDuJianKangApi.AfterSalePushMessageDTO.class);

        BaiDuJianKangApi.AfterSaleDetailRequest orderDetailRequest = new BaiDuJianKangApi.AfterSaleDetailRequest(data.getString("id"), data.getString("storeId"));
        BaiDuJianKangApi.DataRequest<BaiDuJianKangApi.AfterSaleDetailRequest> dataRequest = new BaiDuJianKangApi.DataRequest<BaiDuJianKangApi.AfterSaleDetailRequest>(orderDetailRequest);
        String dataJson = JSON.toJSONString(dataRequest);
        JSONObject sendResult = BaiDuJianKangApi.send(apiCredentialProperties.getBaidus().get(0), null, BaiDuJianKangApi.AFTERSALE_DETAIL, dataJson);
        log.info("请求结果:{}", sendResult);
        if (sendResult != null && sendResult.getIntValue("status", -1) == 0) {
            BaiDuJianKangApi.AfterSaleDetailResponse saleDetail = sendResult.getObject("data", BaiDuJianKangApi.AfterSaleDetailResponse.class);
            /**
             * status	类型	含义
             * 1000	申请售后单（待审核）	申请售后待商家审核
             * 1160	用户寄回（待审核）	用户寄回待商家审核
             * 1300	退款中	售后单退款中
             * 1400	退款成功	售后单退款成功
             * 1310	退款失败	售后单退款失败
             * 1100	用户取消售后	用户取消售后
             * 1200	售后关闭	售后关闭
             */
            CrmAfterSale crmAfterSale = new CrmAfterSale();
            crmAfterSale.setStatus(status);
            switch (status) {
                case 1000:
                    // 售后申请
                    log.info("售后申请:{}", afterSalePushMessageDTO);
                {
                    crmAfterSale = BeanUtil.copyProperties(saleDetail, CrmAfterSale.class);
                    Long orderId = crmAfterSale.getOrderId();
                    CrmOrder crmOrder = crmOrderMapper.selectOne(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getExternalOrderId, orderId));
                    if (crmOrder != null) {
                        List<OrderProductBo> productCollection = crmOrder.getProductCollection();
                        List<AfterSaleOrderProductBo> goods = saleDetail.getGoods().stream().map(goodsInfo -> {
                            AfterSaleOrderProductBo afterSaleOrderProduct = new AfterSaleOrderProductBo();
                            afterSaleOrderProduct.setActualPrice(new BigDecimal(goodsInfo.getUserPayment()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            afterSaleOrderProduct.setOrderPrice(new BigDecimal(goodsInfo.getUserPayment()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            afterSaleOrderProduct.setProductName(goodsInfo.getTitleName());
                            afterSaleOrderProduct.setProductTitle(goodsInfo.getTitleName());
                            afterSaleOrderProduct.setProductImage(goodsInfo.getHeadImgUrl());
                            afterSaleOrderProduct.setNum(goodsInfo.getAmount());
                            afterSaleOrderProduct.setType(ProductType.THIRD_PARTY.getType());
                            Optional<OrderProductBo> orderProductBo = productCollection.stream().filter(f -> f.getExternalPackageId().equals(goodsInfo.getGroupSkuId()) || f.getExternalProductId().equals(goodsInfo.getSkuId())).findFirst();
                            afterSaleOrderProduct.setProductId(orderProductBo.map(OrderProductBo::getProductId).orElse(null));
                            afterSaleOrderProduct.setExternalProductId(orderProductBo.map(OrderProductBo::getExternalProductId).orElse(goodsInfo.getSkuId()));
                            afterSaleOrderProduct.setUnitNum(orderProductBo.map(OrderProductBo::getUnitNum).orElse(null));
                            afterSaleOrderProduct.setProductPrice(orderProductBo.map(OrderProductBo::getProductPrice).orElse(null));
                            afterSaleOrderProduct.setExternalType(orderProductBo.map(OrderProductBo::getExternalType).orElse(null));
                            return afterSaleOrderProduct;
                        }).toList();
                        crmAfterSale.setGoods(goods);

                        SysNotice sysNotice = SysNotice.builder()
                                .noticeTitle("有第三方平台售后单")
                                .noticeType("1")
                                .noticeContent("订单：" + crmOrder.getOrderNo() + "发起了售后,请注意查看!")
                                .sendId(0L)
                                .userId(crmOrder.getSalesmanId())
                                .msgType(MsgType.RETURN.getValue()).build();
                        SpringUtil.publishEvent(sysNotice);
                    } else {
                        log.error("订单不存在:{}", orderId);
                        List<AfterSaleOrderProductBo> goods = saleDetail.getGoods().stream().map(goodsInfo -> {
                            AfterSaleOrderProductBo afterSaleOrderProduct = new AfterSaleOrderProductBo();
                            afterSaleOrderProduct.setActualPrice(new BigDecimal(goodsInfo.getUserPayment()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            afterSaleOrderProduct.setOrderPrice(new BigDecimal(goodsInfo.getUserPayment()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            afterSaleOrderProduct.setProductName(goodsInfo.getTitleName());
                            afterSaleOrderProduct.setProductTitle(goodsInfo.getTitleName());
                            afterSaleOrderProduct.setProductImage(goodsInfo.getHeadImgUrl());
                            afterSaleOrderProduct.setNum(goodsInfo.getAmount());
                            afterSaleOrderProduct.setType(ProductType.THIRD_PARTY.getType());
                            return afterSaleOrderProduct;
                        }).toList();
                        crmAfterSale.setGoods(goods);
                    }
                    crmAfterSale.setCustomerId(Opt.ofNullable(crmOrder).map(CrmOrder::getCustomerId).orElse(null));
                    crmAfterSale.setExternalOrderId(orderId.toString());
                    crmAfterSale.setOrderId(Opt.ofNullable(crmOrder).map(CrmOrder::getOrderId).orElse(null));
                    crmAfterSale.setImageList(saleDetail.getImageList());
                    crmAfterSale.setAfterSaleId(IdWorker.getId());
                    crmAfterSale.setExternalAfterSaleId(saleDetail.getAfterSaleId());
                    crmAfterSale.setAfterSaleType(1);
                    String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.AFTER_SALE_ORDER);
                    crmAfterSale.setAfterSaleNo(sn);
                    crmAfterSaleMapper.insert(crmAfterSale);
                }
                break;
                case 1160:
                    log.info("用户寄回:{}", afterSalePushMessageDTO);
                {
                    crmAfterSale.setReturnDeliverName(saleDetail.getReturnDeliverName());
                    crmAfterSale.setReturnDeliverNo(saleDetail.getReturnDeliverNo());
                    crmAfterSale.setReturnPhone(saleDetail.getReturnPhone());
                    crmAfterSale.setDeliveryPriceFen(saleDetail.getDeliveryPriceFen());
                    crmAfterSale.setSendStatus(saleDetail.getSendStatus());
                }
                break;
                case 1300:
                    log.info("售后单退款中:{}", afterSalePushMessageDTO);
                {
                    crmAfterSale.setReturnTime(DateUtils.date(saleDetail.getReturnTime()));
                    crmAfterSale.setSendStatus(saleDetail.getSendStatus());
                    crmAfterSale.setAfterSaleDeliverInfo(JSONArray.from(saleDetail.getAfterSaleDeliverInfo()));
                }
                break;
                case 1310:
                    log.info("售后单退款失败:{}", afterSalePushMessageDTO);
                {
                    crmAfterSale.setReturnTime(DateUtils.date(saleDetail.getReturnTime()));
                    crmAfterSale.setSendStatus(saleDetail.getSendStatus());
                    crmAfterSale.setAfterSaleDeliverInfo(JSONArray.from(saleDetail.getAfterSaleDeliverInfo()));
                }
                break;
                case 1400:
                    log.info("售后单退款成功:{}", afterSalePushMessageDTO);
                {
                    crmAfterSale.setReturnTime(DateUtils.date(saleDetail.getReturnTime()));
                    crmAfterSale.setSendStatus(saleDetail.getSendStatus());
                    crmAfterSale.setAfterSaleDeliverInfo(JSONArray.from(saleDetail.getAfterSaleDeliverInfo()));
                    crmAfterSale.setReturnTime(DateUtils.date(saleDetail.getReturnTime()));
                    if (saleDetail.getType() == 3) {
                        // 记录库存变化
                        CrmAfterSale foundCrmAfterSale = crmAfterSaleMapper.selectOne(Wrappers.<CrmAfterSale>lambdaQuery().eq(CrmAfterSale::getExternalAfterSaleId, saleDetail.getAfterSaleId()));
                        if (foundCrmAfterSale != null) {
                            List<CrmProductStockRecord> records = foundCrmAfterSale.getGoods().parallelStream().map(item -> {
                                CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                                crmProductStockRecord.setOperationType(1);
                                crmProductStockRecord.setOrderId(foundCrmAfterSale.getOrderId());
                                crmProductStockRecord.setProductId(item.getProductId());
                                crmProductStockRecord.setOrderStatus(3);
                                crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum() / item.getUnitNum()));
                                return crmProductStockRecord;
                            }).toList();
                            crmProductStockRecordMapper.insert(records);
                        }

                    }
                }
                break;
                case 1100:
                    log.info("用户取消售后:{}", afterSalePushMessageDTO);
                {

                }
                break;
                case 1200:
                    log.info("售后关闭:{}", afterSalePushMessageDTO);
                {
                    crmAfterSale.setReturnTime(DateUtils.date(saleDetail.getReturnTime()));
                    crmAfterSale.setSendStatus(saleDetail.getSendStatus());
                    crmAfterSale.setAfterSaleDeliverInfo(JSONArray.from(saleDetail.getAfterSaleDeliverInfo()));
                }
                break;
            }

            if (status != 1000) {
                crmAfterSaleMapper.update(crmAfterSale, Wrappers.<CrmAfterSale>lambdaQuery().eq(CrmAfterSale::getExternalAfterSaleId, afterSalePushMessageDTO.getId()));
            }
        } else {
            log.error("监听售后异常：{}", data);
            log.error("监听售后异常结果：{}", sendResult);
            throw new ServiceException("监听售后异常");
        }

        return 1;
    }
}
